package com.lovely602.langchain4j.mcp.controller;


import com.lovely602.langchain4j.mcp.service.McpService;
import dev.langchain4j.mcp.McpToolProvider;
import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.McpClient;
import dev.langchain4j.mcp.client.transport.McpTransport;
import dev.langchain4j.mcp.client.transport.stdio.StdioMcpTransport;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.tool.ToolProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.Map;

/**
 *
 * 第1步，如何进行mcp编码
 *  https://docs.langchain4j.dev/tutorials/mcp#creating-an-mcp-tool-provider
 *
 * 第2步，如何使用baidu map mcp，它提供了哪些功能对外服务
 *  https://mcp.so/zh/server/baidu-map/baidu-maps?tab=tools
 *
 * http://localhost:9014/mcp/chat?question=查询61.149.121.66归属地
 * http://localhost:9014/mcp/chat?question=查询北京天气
 * http://localhost:9014/mcp/chat?question=查询昌平到天安门路线规划
 *
 * @author lizhixing
 */
@Slf4j
@RestController
@RequestMapping("/mcp")
public class MCPController {

    @Autowired
    private StreamingChatModel streamingChatModel;

    /**
     * 测试调用高德地图mcp
     */
    @GetMapping("/amap/chat")
    public Flux<String> amapChat(@RequestParam("msg") String msg) throws Exception {
        String apiKey = System.getenv("AMAP_MAPS_API_KEY");
        if (apiKey == null || apiKey.isEmpty()) {
            log.error("AMAP_MAPS_API_KEY environment variable is not set");
            return Flux.just("Error: 高德地图API密钥未配置");
        }

        McpTransport transport = null;
        McpClient mcpClient = null;

        try {
            transport = new StdioMcpTransport.Builder()
                    .command(List.of("cmd", "/c", "npx", "-y", "@amap/amap-maps-mcp-server"))
                    .environment(Map.of("AMAP_MAPS_API_KEY", apiKey))
                    .logEvents(true)
                    .build();

            mcpClient = new DefaultMcpClient.Builder()
                    .clientName("高德地图")
                    .transport(transport)
                    .build();

            ToolProvider toolProvider = McpToolProvider.builder()
                    .mcpClients(mcpClient)
                    .build();

            McpService mcpService = AiServices.builder(McpService.class)
                    .streamingChatModel(streamingChatModel)
                    .toolProvider(toolProvider)
                    .build();

            return mcpService.chat(msg);

        } catch (Exception e) {
            log.error("Error in MCP chat processing", e);
            return Flux.just("处理请求时发生错误: " + e.getMessage());
        } finally {
            if (mcpClient != null) {
                try {
                    mcpClient.close();
                } catch (Exception closeException) {
                    log.warn("Error closing MCP client", closeException);
                }
            }
        }
    }

    /**
     * 测试调用百度地图mcp
     */
    @GetMapping("/baidumap/chat")
    public Flux<String> chat(@RequestParam("msg") String msg) throws Exception {
        String apiKey = System.getenv("BAIDU_MAP_API_KEY");
        if (apiKey == null || apiKey.isEmpty()) {
            log.error("BAIDU_MAP_API_KEY environment variable is not set");
            return Flux.just("Error: 百度地图API密钥未配置");
        }

        McpTransport transport = null;
        McpClient mcpClient = null;

        try {
            /**1.构建McpTransport协议
             *
             * 1.1 cmd：启动 Windows 命令行解释器。
             * 1.2 /c：告诉 cmd 执行完后面的命令后关闭自身。
             * 1.3 npx：npx = npm execute package，Node.js 的一个工具，用于执行 npm 包中的可执行文件。
             * 1.4 -y 或 --yes：自动确认操作（类似于默认接受所有提示）。
             * 1.5 @baidumap/mcp-server-baidu-map：要通过 npx 执行的 npm 包名
             * 1.6 BAIDU_MAP_API_KEY 是访问百度地图开放平台API的AK
             */
            transport = new StdioMcpTransport.Builder()
                    .command(List.of("cmd", "/c", "npx", "-y", "@baidumap/mcp-server-baidu-map"))
                    .environment(Map.of("BAIDU_MAP_API_KEY", apiKey))
                    .logEvents(true)
                    .build();

            mcpClient = new DefaultMcpClient.Builder()
                    .clientName("百度地图")
                    .transport(transport)
                    .build();

            ToolProvider toolProvider = McpToolProvider.builder()
                    .mcpClients(mcpClient)
                    .build();

            McpService mcpService = AiServices.builder(McpService.class)
                    .streamingChatModel(streamingChatModel)
                    .toolProvider(toolProvider)
                    .build();

            return mcpService.chat(msg);

        } catch (Exception e) {
            log.error("Error in MCP chat processing", e);
            return Flux.just("处理请求时发生错误: " + e.getMessage());
        } finally {
            if (mcpClient != null) {
                try {
                    mcpClient.close();
                } catch (Exception closeException) {
                    log.warn("Error closing MCP client", closeException);
                }
            }
        }
    }
}
